Skip to content

Refactor: Split main.rs into modular structure#24

Merged
cbaugus merged 7 commits intomainfrom
feature/issue-15-modular-refactor
Feb 10, 2026
Merged

Refactor: Split main.rs into modular structure#24
cbaugus merged 7 commits intomainfrom
feature/issue-15-modular-refactor

Conversation

@cbaugus
Copy link
Owner

@cbaugus cbaugus commented Feb 9, 2026

Summary

  • Split the monolithic 794-line main.rs into 7 focused modules
  • main.rs reduced to 79 lines acting as entry point only
  • All existing functionality preserved with zero behavioral changes
  • Added comprehensive test suite: 79 tests total (67 unit + 12 integration)
  • Enhanced CI/CD pipeline with automated testing and linting
  • Added proper error handling and validation to Config with descriptive messages
  • Implemented structured logging with tracing for better observability

Module Structure

Module Responsibility Tests
main.rs (79 lines) Entry point, orchestration -
lib.rs (6 lines) Module exports -
config.rs Config struct, env var parsing, validation 21 unit
load_models.rs LoadModel enum, RPS calculations 22 unit
client.rs HTTP client builder, TLS/mTLS, DNS override -
metrics.rs Prometheus metrics, handler, server -
worker.rs Async worker task logic -
utils.rs Duration parsing, header parsing 22 unit
tests/integration_test.rs End-to-end tests with mock server 12 integration

Test Coverage

Unit Tests (67)

  • LoadModel: 22 tests (all variants, phase transitions, edge cases)
  • utils: 22 tests (duration parsing, header parsing)
  • config: 21 tests (defaults, all load models, validation, error cases)

Integration Tests (12)

  • GET/POST requests with mock HTTP server (wiremock)
  • JSON payload handling and Content-Type headers
  • Status code tracking (200, 404, 500, errors)
  • Metrics recording (requests_total, duration, concurrent gauge)
  • Connection error handling
  • RPS rate limiting validation
  • Slow response handling

Error Handling Improvements

ConfigError Enum - Descriptive error types:

  • MissingEnvVar - Required environment variables
  • InvalidValue - Parse errors with context
  • InvalidUrl - URL format validation
  • InvalidDuration - Duration parsing errors
  • IncompleteMtls - mTLS cert/key consistency
  • MissingLoadModelParams - Load model requirements

Validation:

  • URL format (must start with http:// or https://)
  • NUM_CONCURRENT_TASKS > 0
  • mTLS requires both cert and key, or neither
  • Helpful error messages with configuration documentation

Benefits:

  • No more panics on invalid configuration
  • Clear error messages explain what's wrong and how to fix it
  • Help text printed automatically on configuration errors
  • Config::for_testing() helper for unit tests

Structured Logging

Tracing Integration:

  • Replaced all println!/eprintln! with structured logging
  • Log levels: error, warn, info, debug, trace
  • Structured fields for filtering and searching
  • Timestamps and thread IDs included
  • JSON output format support

Configuration:

  • RUST_LOG - Control log level (e.g., info, debug, rust_loadtest=trace)
  • LOG_FORMAT=json - Enable JSON output for log aggregation

Log Levels:

  • error: Configuration errors, request failures
  • warn: DailyTraffic ratio warnings
  • info: Test lifecycle, configuration summary, metrics
  • debug: Worker lifecycle, individual requests with latency

Benefits:

  • Better debugging and observability
  • Integrates with log aggregation systems
  • Filters by level, module, or field values
  • Production-ready JSON output

CI/CD Pipeline

New Jobs:

  1. Lint - Runs first on every push/PR

    • cargo fmt --check (enforce code formatting)
    • cargo clippy -- -D warnings (treat warnings as errors)
    • Caches cargo registry and build artifacts
  2. Test - Runs after lint passes

    • cargo test --all-features --verbose
    • Runs all 79 tests (67 unit + 12 integration)
    • Caches dependencies for faster runs
  3. Build - Runs after tests pass

    • Builds Docker images (Ubuntu + Chainguard)
    • Generates SBOMs with Syft
    • Only pushes images on push events (not PRs)

Pipeline Flow: Lint → Test → Build → Push

Verification

  • cargo build compiles successfully
  • cargo fmt --check passes
  • cargo clippy passes with no warnings
  • cargo test - all 79 tests pass (67 unit + 12 integration)
  • Configuration error handling works correctly
  • Structured logging tested (info, debug, JSON formats)
  • CI pipeline passes in GitHub Actions
  • Docker images build correctly
  • Verify load test behavior unchanged against target endpoint

Closes #15, Closes #16, Closes #17, Closes #18, Closes #19, Closes #20, Closes #21, Closes #22, Closes #23

Split the 794-line main.rs into focused modules for better
maintainability, testability, and code organization.

Closes #15

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- LoadModel: 22 tests covering all 4 variants (Concurrent, Rps,
  RampRps, DailyTraffic) including phase transitions, boundary
  values, cycle wrapping, and edge cases
- parse_duration_string: 15 tests covering valid formats (m/h/d),
  whitespace trimming, and error cases (empty, invalid suffix,
  fractional, negative, non-numeric)
- Config: 16 tests covering defaults, all load model types,
  optional fields, JSON payload, and panic on missing required vars

Total: 62 tests passing (up from 7)

Closes #16, Closes #17, Closes #18

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- 12 integration tests covering end-to-end worker behavior
- Tests GET/POST requests, JSON payloads, status code tracking
- Tests metrics recording (requests_total, duration, status codes)
- Tests error handling (connection refused, timeouts)
- Tests RPS rate limiting with timing validation
- Tests slow response handling

All tests use wiremock 0.5 for mock HTTP server

Total: 74 tests passing (62 unit + 12 integration)

Closes #19

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add lint job: cargo fmt --check, cargo clippy -- -D warnings
- Add test job: cargo test --all-features --verbose
- Build job now depends on test passing (test depends on lint)
- Added caching for cargo registry and build artifacts
- Only push Docker images on push events (not PRs)
- Format all source code with cargo fmt

CI pipeline now enforces:
- Code formatting (rustfmt)
- Lint rules (clippy with warnings as errors)
- All tests passing (74 tests: 62 unit + 12 integration)

Closes #20, Closes #21

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
cbaugus and others added 3 commits February 9, 2026 16:41
Implemented issue #23:
- Added ConfigError enum with descriptive error types
- Replaced all .expect() calls with proper error returns
- Added validate() method for URL, concurrent tasks, and mTLS validation
- Added helper functions: env_required(), env_parse_or(), env_bool()
- Added Config::for_testing() for test support
- Updated main.rs to print helpful error messages on config failure
- Updated all tests to check for proper errors instead of panics
- Added 5 new validation tests

All 79 tests passing (67 unit + 12 integration)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implemented issue #22:
- Added tracing and tracing-subscriber dependencies
- Initialized tracing subscriber with RUST_LOG and LOG_FORMAT support
- Replaced all println!/eprintln! with structured logging
- Added log levels: error, warn, info, debug
- Added structured fields to all log messages
- Worker lifecycle logging (starting, stopping, request completion)
- JSON output format support for log aggregation
- Updated help text with logging configuration
- Added .gitignore for build artifacts

Features:
- RUST_LOG env var controls log level (error/warn/info/debug/trace)
- LOG_FORMAT=json enables JSON output for log aggregation
- Structured fields for filtering and searching
- Timestamps and thread IDs included
- Module targeting supported

All 79 tests passing (67 unit + 12 integration)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@cbaugus cbaugus force-pushed the feature/issue-15-modular-refactor branch from 70774f5 to 4b7bb03 Compare February 10, 2026 16:37
@cbaugus cbaugus merged commit 6e5648a into main Feb 10, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment